{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Naive Bayes Hidden Markov Coin Toss"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "author: Nicholas Farn [<a href=\"sendto:nicholasfarn@gmail.com\">nicholasfarn@gmail.com</a>]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example we will be using a simple Hidden Markov Model to demonstrate how it can be used in a Naive Bayes classifier. In this particular example we have a couple friends who enjoy playing a game of chance. Someone tosses a coin and whenever it lands on heads, the tosser gains \\$1, otherwise he pays \\$1. However some of our friends are prone to using rigged coins in order to come out ahead in the long run.\n",
    "\n",
    "Players fall into 3 categories, non-cheaters, smart cheaters, and dumb cheaters. Non-cheaters, as the name implies, do not use rigged coins. Smart cheaters make sure to switch between rigged and unrigged coins in order to keep the deception going. Dumb cheaters only use rigged coins."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Populating the interactive namespace from numpy and matplotlib\n"
     ]
    }
   ],
   "source": [
    "from pomegranate import *\n",
    "import numpy as np\n",
    "%pylab inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start by creating our hmm's. Since this is a simple example, we will only have 2 states, rigged and unrigged, with discrete distributions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "rigged = State( DiscreteDistribution({'H': 0.8, 'T': 0.2}), name=\"rigged\" )\n",
    "unrigged = State( DiscreteDistribution({'H': 0.5, 'T': 0.5}), name=\"unrigged\" )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's create our non-cheater and dumb cheater since their hmm's consist of a single state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "non_cheater = HiddenMarkovModel( name=\"non-cheater\" )\n",
    "non_cheater.add_state( unrigged )\n",
    "\n",
    "dumb_cheater = HiddenMarkovModel( name=\"dumb-cheater\" )\n",
    "dumb_cheater.add_state( rigged )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now add our starting states to our models."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "non_cheater.start = unrigged\n",
    "dumb_cheater.start = rigged"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also add the transitions to our non-cheater and dumb cheater."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "non_cheater.add_transition( unrigged, unrigged, 1 )\n",
    "dumb_cheater.add_transition( rigged, rigged, 1 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we bake our models to finalize the structure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "non_cheater.bake()\n",
    "dumb_cheater.bake()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can create our smart cheater."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "smart_cheater = HiddenMarkovModel( name=\"smart-cheater\" )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The structure of our smart cheater hmm should look like the following."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's add in our starting transitions. Smart cheaters start out half the time with an unrigged coin, half the time without."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "smart_cheater.add_transition( smart_cheater.start, unrigged, 0.5 )\n",
    "smart_cheater.add_transition( smart_cheater.start, rigged, 0.5 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we can add our transition matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "smart_cheater.add_transition( rigged, rigged, 0.5 )\n",
    "smart_cheater.add_transition( rigged, unrigged, 0.5 )\n",
    "smart_cheater.add_transition( unrigged, rigged, 0.5 )\n",
    "smart_cheater.add_transition( unrigged, unrigged, 0.5 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally we can bake the model to finalize its structure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "smart_cheater.bake()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can view the structures of all our hmm's in the images below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"smart cheater hmm\")\n",
    "smart_cheater.plot()\n",
    "\n",
    "plt.title(\"dumb cheater hmm\")\n",
    "dumb_cheater.plot()\n",
    "\n",
    "plt.title(\"non-cheater hmm\")\n",
    "non_cheater.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can finally create our Naive Bayes classifier. We'll let 0 stand for a non-cheater, 1 stand for a smart cheater, and 2 stand for a dumb cheater."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "players = NaiveBayes([ non_cheater, smart_cheater, dumb_cheater ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's create a sequence of coin tosses to test our classifier on."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = np.array([list( 'HHHHHTHTHTTTTHHHTHHTTHHHHHTH' ),\n",
    "                 list( 'HHHHHHHTHHHHTTHHHHHHHTTHHHHH' ),\n",
    "                 list( 'THTHTHTHTHTHTTHHTHHHHTTHHHTT' )])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now check the log probability of each string of data occurring under each model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "For sequence 1, 21.4% non-cheater, 68.0% smart cheater, 10.6% dumb cheater.\n",
      "For sequence 2, 0.173% non-cheater, 12.1% smart cheater, 87.7% dumb cheater.\n",
      "For sequence 3, 66.5% non-cheater, 33.0% smart cheater, 0.515% dumb cheater.\n"
     ]
    }
   ],
   "source": [
    "probs = players.predict_proba( data )\n",
    "\n",
    "for i in range(len(probs)):\n",
    "    print(\"For sequence {}, {:.3}% non-cheater, {:.3}% smart cheater, {:.3}% dumb cheater.\".format( i+1, 100*probs[i][0], 100*probs[i][1], 100*probs[i][2]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally we can classify whether a non-cheater (0), smart cheater (1), or dumb cheater (2) created the string of data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sequence 1 is a smart cheater\n",
      "Sequence 2 is a dumb cheater\n",
      "Sequence 3 is a non-cheater\n"
     ]
    }
   ],
   "source": [
    "output = players.predict( data )\n",
    "\n",
    "for i in range(len(output)):\n",
    "    print(\"Sequence {} is a {}\".format( i+1, \"non-cheater\" if output[i] == 0 else \"smart cheater\" if output[i] == 1 else \"dumb cheater\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also train our hmm's through Naive Bayes. Let's used the following data, all marked as known games for smart cheaters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([list( 'HHHHHTHTHTTTTH' ),\n",
    "              list( 'HHTHHTTHHHHHTH' )])\n",
    "\n",
    "y = np.array([ 1, 1 ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's fit our NaiveBayes classifier to our data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "    \"class\" : \"NaiveBayes\",\n",
       "    \"models\" : [\n",
       "        {\n",
       "            \"class\" : \"HiddenMarkovModel\",\n",
       "            \"name\" : \"non-cheater\",\n",
       "            \"start\" : {\n",
       "                \"class\" : \"State\",\n",
       "                \"distribution\" : {\n",
       "                    \"class\" : \"Distribution\",\n",
       "                    \"dtype\" : \"str\",\n",
       "                    \"name\" : \"DiscreteDistribution\",\n",
       "                    \"parameters\" : [\n",
       "                        {\n",
       "                            \"H\" : 0.49218749999999994,\n",
       "                            \"T\" : 0.5078125000000001\n",
       "                        }\n",
       "                    ],\n",
       "                    \"frozen\" : false\n",
       "                },\n",
       "                \"name\" : \"unrigged\",\n",
       "                \"weight\" : 1.0\n",
       "            },\n",
       "            \"end\" : {\n",
       "                \"class\" : \"State\",\n",
       "                \"distribution\" : null,\n",
       "                \"name\" : \"non-cheater-end\",\n",
       "                \"weight\" : 1.0\n",
       "            },\n",
       "            \"states\" : [\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : {\n",
       "                        \"class\" : \"Distribution\",\n",
       "                        \"dtype\" : \"str\",\n",
       "                        \"name\" : \"DiscreteDistribution\",\n",
       "                        \"parameters\" : [\n",
       "                            {\n",
       "                                \"H\" : 0.49218749999999994,\n",
       "                                \"T\" : 0.5078125000000001\n",
       "                            }\n",
       "                        ],\n",
       "                        \"frozen\" : false\n",
       "                    },\n",
       "                    \"name\" : \"unrigged\",\n",
       "                    \"weight\" : 1.0\n",
       "                },\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : null,\n",
       "                    \"name\" : \"non-cheater-end\",\n",
       "                    \"weight\" : 1.0\n",
       "                }\n",
       "            ],\n",
       "            \"end_index\" : 1,\n",
       "            \"start_index\" : 0,\n",
       "            \"silent_index\" : 1,\n",
       "            \"edges\" : [\n",
       "                [\n",
       "                    0,\n",
       "                    0,\n",
       "                    1.0,\n",
       "                    1,\n",
       "                    null\n",
       "                ]\n",
       "            ],\n",
       "            \"distribution ties\" : []\n",
       "        },\n",
       "        {\n",
       "            \"class\" : \"HiddenMarkovModel\",\n",
       "            \"name\" : \"smart-cheater\",\n",
       "            \"start\" : {\n",
       "                \"class\" : \"State\",\n",
       "                \"distribution\" : null,\n",
       "                \"name\" : \"smart-cheater-start\",\n",
       "                \"weight\" : 1.0\n",
       "            },\n",
       "            \"end\" : {\n",
       "                \"class\" : \"State\",\n",
       "                \"distribution\" : null,\n",
       "                \"name\" : \"smart-cheater-end\",\n",
       "                \"weight\" : 1.0\n",
       "            },\n",
       "            \"states\" : [\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : {\n",
       "                        \"class\" : \"Distribution\",\n",
       "                        \"dtype\" : \"str\",\n",
       "                        \"name\" : \"DiscreteDistribution\",\n",
       "                        \"parameters\" : [\n",
       "                            {\n",
       "                                \"H\" : 0.7949526813880127,\n",
       "                                \"T\" : 0.2050473186119874\n",
       "                            }\n",
       "                        ],\n",
       "                        \"frozen\" : false\n",
       "                    },\n",
       "                    \"name\" : \"rigged\",\n",
       "                    \"weight\" : 1.0\n",
       "                },\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : {\n",
       "                        \"class\" : \"Distribution\",\n",
       "                        \"dtype\" : \"str\",\n",
       "                        \"name\" : \"DiscreteDistribution\",\n",
       "                        \"parameters\" : [\n",
       "                            {\n",
       "                                \"H\" : 0.49218749999999994,\n",
       "                                \"T\" : 0.5078125000000001\n",
       "                            }\n",
       "                        ],\n",
       "                        \"frozen\" : false\n",
       "                    },\n",
       "                    \"name\" : \"unrigged\",\n",
       "                    \"weight\" : 1.0\n",
       "                },\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : null,\n",
       "                    \"name\" : \"smart-cheater-start\",\n",
       "                    \"weight\" : 1.0\n",
       "                },\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : null,\n",
       "                    \"name\" : \"smart-cheater-end\",\n",
       "                    \"weight\" : 1.0\n",
       "                }\n",
       "            ],\n",
       "            \"end_index\" : 3,\n",
       "            \"start_index\" : 2,\n",
       "            \"silent_index\" : 2,\n",
       "            \"edges\" : [\n",
       "                [\n",
       "                    2,\n",
       "                    1,\n",
       "                    0.5,\n",
       "                    0.5,\n",
       "                    null\n",
       "                ],\n",
       "                [\n",
       "                    2,\n",
       "                    0,\n",
       "                    0.5,\n",
       "                    0.5,\n",
       "                    null\n",
       "                ],\n",
       "                [\n",
       "                    1,\n",
       "                    0,\n",
       "                    0.5,\n",
       "                    0.5,\n",
       "                    null\n",
       "                ],\n",
       "                [\n",
       "                    1,\n",
       "                    1,\n",
       "                    0.5,\n",
       "                    0.5,\n",
       "                    null\n",
       "                ],\n",
       "                [\n",
       "                    0,\n",
       "                    0,\n",
       "                    0.5,\n",
       "                    0.5,\n",
       "                    null\n",
       "                ],\n",
       "                [\n",
       "                    0,\n",
       "                    1,\n",
       "                    0.5,\n",
       "                    0.5,\n",
       "                    null\n",
       "                ]\n",
       "            ],\n",
       "            \"distribution ties\" : []\n",
       "        },\n",
       "        {\n",
       "            \"class\" : \"HiddenMarkovModel\",\n",
       "            \"name\" : \"dumb-cheater\",\n",
       "            \"start\" : {\n",
       "                \"class\" : \"State\",\n",
       "                \"distribution\" : {\n",
       "                    \"class\" : \"Distribution\",\n",
       "                    \"dtype\" : \"str\",\n",
       "                    \"name\" : \"DiscreteDistribution\",\n",
       "                    \"parameters\" : [\n",
       "                        {\n",
       "                            \"H\" : 0.7949526813880127,\n",
       "                            \"T\" : 0.2050473186119874\n",
       "                        }\n",
       "                    ],\n",
       "                    \"frozen\" : false\n",
       "                },\n",
       "                \"name\" : \"rigged\",\n",
       "                \"weight\" : 1.0\n",
       "            },\n",
       "            \"end\" : {\n",
       "                \"class\" : \"State\",\n",
       "                \"distribution\" : null,\n",
       "                \"name\" : \"dumb-cheater-end\",\n",
       "                \"weight\" : 1.0\n",
       "            },\n",
       "            \"states\" : [\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : {\n",
       "                        \"class\" : \"Distribution\",\n",
       "                        \"dtype\" : \"str\",\n",
       "                        \"name\" : \"DiscreteDistribution\",\n",
       "                        \"parameters\" : [\n",
       "                            {\n",
       "                                \"H\" : 0.7949526813880127,\n",
       "                                \"T\" : 0.2050473186119874\n",
       "                            }\n",
       "                        ],\n",
       "                        \"frozen\" : false\n",
       "                    },\n",
       "                    \"name\" : \"rigged\",\n",
       "                    \"weight\" : 1.0\n",
       "                },\n",
       "                {\n",
       "                    \"class\" : \"State\",\n",
       "                    \"distribution\" : null,\n",
       "                    \"name\" : \"dumb-cheater-end\",\n",
       "                    \"weight\" : 1.0\n",
       "                }\n",
       "            ],\n",
       "            \"end_index\" : 1,\n",
       "            \"start_index\" : 0,\n",
       "            \"silent_index\" : 1,\n",
       "            \"edges\" : [\n",
       "                [\n",
       "                    0,\n",
       "                    0,\n",
       "                    1.0,\n",
       "                    1,\n",
       "                    null\n",
       "                ]\n",
       "            ],\n",
       "            \"distribution ties\" : []\n",
       "        }\n",
       "    ],\n",
       "    \"weights\" : [\n",
       "        0.0,\n",
       "        1.0,\n",
       "        0.0\n",
       "    ]\n",
       "}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "players.fit( X, y )"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
